"""
   This is the source file for the text-based user interface. It's nice
   and simple and has a shell.
"""
import sys, os
import thread
import binascii
import string
import threading
import traceback

import fileT
from network import EntangledNetworkLayer
from listen import Listener
from ui_abstract import AbstractUI
import twisted.internet.reactor

class TextUI(AbstractUI):
    noResultsStr = "No results found!"
    searchResults = [[[]]]
    numInResults = 0
    numResultCategories = 0
    semaphore = None

    def __init__(self, myPort, ip, port, shareDirs):
        if ip == "":
            ip = raw_input("Connect IP: ")
            print ip
        if ip != "" and port == -1:
            portStr = raw_input("Connect port: ")
            if portStr == "":
                port = 1337
            else:
                port = int(portStr)

        self.semaphore = threading.Semaphore(1)
        AbstractUI.__init__(self, myPort, ip, port, shareDirs)

    def do_searchDisplay(self, result):
        self.semaphore.acquire()

        #Sanity check
        if len(result) == 0:
           self.semaphore.release()
           return

        for key,value in result.iteritems():
            printVal = 1
            splitValue = value.split(",")
            if self.numInResults == 0:
                #If we're empty, the hash check doesn't need to happen
                self.searchResults.append([value])
                self.numInResults = 1
                self.numResultCategories = 1
            else:
                loopBreak = 0
                #The results string is not empty. We have to either:
                #1. Find a preexisting search result with the same file hash, or
                #2. Insert at the end of the list
                for a in range(0,len(self.searchResults)):
                   for b in range(0,len(self.searchResults[a])):
                      if splitValue[3] == self.searchResults[a][b].split(",")[3]:
                         self.searchResults[a].append(value)
                         loopBreak = 1
                         printVal = 0 #Already in list, don't need to print
                         self.numInResults = self.numInResults + 1
                         break
                   if loopBreak: break
                if loopBreak == 0:
                   self.searchResults.append([value])
                   self.numInResults = self.numInResults + 1
                   self.numResultCategories = self.numResultCategories + 1


            if printVal:
               print str(self.numResultCategories)+": " + os.path.split(splitValue[2])[1] + ":"
               print "\tRemote IP:Port: " + splitValue[0] + ":" + splitValue[1]
               print "\tFile hash: " + splitValue[3]
               print

        self.semaphore.release()

    def filePublished(self, result):
        print result
        
    #Stubs for callback methods, put more interesting things in here later
    def getFile(self, getNum):
        if len(getNum) == 1:
            getNum = [raw_input("Enter search result number to download file: ")]
        else: del getNum[0]

        if self.numInResults==0:
            print "No search has been performed yet!"
            return
        for i in getNum:
            self.download(self.searchResults[int(i)-1])
         
    def download(self, result):
    	#resultList = string.split(result,',')
        #filelist = string.split(result,' ')
        #[file file file     ] [ip port path hash]
      pas = []
      for i in result:
         resultList = i.split(',')
         dlTuple = (resultList[0], resultList[1], resultList[2])
         pas.append(dlTuple)
      fileT.file_recieve_request(pas).start()

            

    #Some private functions used by the run loop
    def __printHelp(self):
        print "\nCommands:"
        print "help - display this message"
        print "share - select a folder or file to share, display shared files"
        print "search - search for a file by keyword"
        print "get - download file by search number, filename, or hash"
        print "exit - quit program\n"

    def __getSearch(self, search):
        if len(search) == 1:
            return raw_input("Enter search terms: ").split()
        del search[0]

        #Convert to all lower case since that's how Entangled works apparently
        return [i.lower() for i in search]

    def __publishAllInDirs(self, directories, network):
        if len(directories) == 1:
            AbstractUI.__publishAllInDirs__(self, [raw_input("Directory to share: ")], network)
        else:
            del directories[0]
            AbstractUI.__publishAllInDirs__(self, directories, network)

    #Main run loop
    def run(self, network):
        self.__printHelp()

        try:
            while(1):
                #twisted.internet.reactor.runUntilCurrent()
                #t = twisted.internet.reactor.timeout()
                #t2 = twisted.internet.reactor.running and t
                #twisted.internet.reactor.doIteration(t2)

                inputStr = raw_input("?> ").split()
                if len(inputStr) == 0:
                    continue
                if inputStr[0] == "exit":
                    break
                if inputStr[0] == "help":
                    self.__printHelp()
                    continue
                if inputStr[0] == "share":
                    self.__publishAllInDirs(inputStr, network)
                    continue
                if inputStr[0] == "search":
                    self.searchResults = []
                    self.numInResults = 0
                    network.search(self.__getSearch(inputStr))
                    continue
                if inputStr[0] == "get":
                    #I'm just using a dummy key at the moment to test this myself.
                    #It won't work on your computer. Change it to some file in a directory you share.
                    self.getFile(inputStr)
                    continue
                if inputStr[0] == "results":
                   print self.searchResults
                   continue
                print "Unknown command, type help for command list"
        except(KeyboardInterrupt, SystemExit):
            print
            return
        except:
            traceback.print_exc()
